use std::{collections::HashMap, fmt::Debug, time::Duration};

use axum::http::HeaderValue;

use lazy_static::lazy_static;
pub mod config;
pub use config::*;
pub mod namespaces;
pub use namespaces::*;
pub mod instance;
pub use instance::*;

pub mod login;
pub use login::*;
pub mod request_response;
pub use request_response::*;

use serde::Serialize;
// use serde_json::json;

use tokio::sync::Mutex;
use tracing::info;

use crate::ServerConfig;

lazy_static! {
    pub static ref LOGIN_TOKEN: Mutex<HashMap<String, LoginRes>> ={
        let mut  map = HashMap::<String, LoginRes>::new();
        map.insert(String::from("token"), LoginRes{
            global_admin:true,
            username:"nacos".to_string(),
            access_token:"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTY2MzgzNzI4OH0.u2P86OolPCQMHGiv2_4VSNqkJuDdnMYfry1q_GqFng0".to_string(),
            token_ttl:0,
        });
        Mutex::new(map)
    };

    // pub static ref LOGIN_CONFIG: Mutex<HashMap<String, Login>> =
    //     Mutex::new(HashMap::<String, Login>::new());
    pub static ref BASE_URL: String = "http://10.0.8.4:8848".to_string();
}

// #[derive(Debug, Clone, Default, Serialize, Deserialize)]
// pub struct ComplexInfo<T>(T);

pub async fn normal_handler<REQ>(req: &Request<REQ>) -> anyhow::Result<Response>
where
    REQ: Serialize + Clone + Debug,
{
    tracing::info!("normal_handler 接收信息为 {:?}", &req);
    // let data = serde_json::to_string(&req.data.clone())?;
    // tracing::info!("data={data:?}");
    // let json = serde_json::from_str(data.as_str())?;

    //    let json_map:Map<String,String> = serde_json::Map::new();
    // tracing::info!("json={json:?}");
    let reqest = req.url.convert().await?;
    let mut url = reqest.0;
    let method = reqest.1;

    // let map = match json {
    //     serde_json::Value::Object(v) => Some(v),
    //     _ => None,
    // };
    // tracing::info!("map: {:?}", map);
    // if let Some(v) = map {
    let client = reqwest::ClientBuilder::new().build()?;

    let headers = if req.headers.is_some() {
        req.headers.clone().unwrap_or_default()
    } else {
        Default::default()
    };

    let value = serde_json::to_vec(&req.data)?;
    // let value = json!(req.data);
    // let req_data: serde_json::Map<std::string::String, serde_json::Value> =
    // serde_json::from_value(value).unwrap();
    let req_data: HashMap<String, String> = serde_json::from_slice(&value)?;
    tracing::info!("req_data: {req_data:?}",);
    let res = match req.content_type {
        RequestContentType::Form => {
            url = url.replace("\"", "");
            tracing::info!("url {:?}", url);
            client
                .request(method, url)
                .headers(headers)
                .form(&req_data)
                .send()
                .await
        }
        RequestContentType::Json => {
            req_data
                .iter()
                // .filter(|e| !e.1.eq(&"".to_string()))
                .for_each(|e| {
                    url.push_str(&format!("&{}={:?}", e.0, e.1));
                });
            url = url.replace("\"", "");
            tracing::info!("url {:?}", &url);
            client
                .request(method, url)
                .headers(headers)
                // .form(&req_data)
                .send()
                .await
        }
        RequestContentType::Default => {
            req_data
                .iter()
                // .filter(|e| !e.1.eq(&"".to_string()))
                .for_each(|e| {
                    url.push_str(&format!("&{}={:?}", e.0, e.1));
                });
            url = url.replace("\"", "");
            tracing::info!("url {:?}", &url);
            client
                .request(method, url)
                .headers(headers)
                // .form(&req_data)
                .send()
                .await
        }
    };
    tracing::info!("response {:?}", &res);

    match res {
        Ok(value) => {
            let mut params = HashMap::<String, HeaderValue>::default();

            let headers = value.headers();
            for v in headers.iter() {
                params.insert(v.0.to_string(), v.1.clone());
            }

            tracing::info!("headers={headers:?}");
            let data = value.text().await?;
            tracing::info!("data={data:?}");
            Ok(Response {
                data: Some(data),
                headers: Some(params),
            })
        }
        Err(_) => Err(anyhow::format_err!("12222")),
    }
}

pub async fn register_nacos(config: ServerConfig) {
    let service_name = match config.server_name {
        Some(v) => v,
        None => String::from("nacos"),
    };
    let group_name = match config.group_name {
        Some(v) => v,
        None => String::from("DEFAULT_GROUP"),
    };
    let namespace_id = match config.namespace_id {
        Some(v) => v,
        None => String::from(""),
    };
    let protect_threshold = match config.protect_threshold {
        Some(v) => v,
        None => String::from("0.0"),
    };
    let metadata = match config.metadata {
        Some(v) => v,
        None => String::from(""),
    };
    let selector = match config.selector {
        Some(v) => v,
        None => String::from("none"),
    };
    let port = match config.port {
        Some(v) => String::from(v.to_string()),
        None => String::from("80"),
    };
    let ip = match config.host {
        Some(ip) => ip,
        None => local_ipaddress::get().unwrap(),
    };

    register_service(
        &service_name,
        &group_name,
        &namespace_id,
        &protect_threshold,
        &metadata,
        &selector,
    )
    .await;
    //注册实例
    let instance_req = Request {
        data: Instance {
            ip: ip.clone(),
            port: port.clone(),
            namespace_id: namespace_id.clone(),
            weight: String::from("1"),
            enabled: String::from("true"),
            healthy: String::from("true"),
            metadata: metadata.clone(),
            cluster_name: String::from("DEFAULT"),
            service_name: service_name.clone(),
            group_name: group_name.clone(),
            ephemeral: String::from("true"),
        },
        url: RequestUrl::PostServiceInstance,
        headers: Default::default(),
        content_type: Default::default(),
    };

    let instance_health = Request {
        data: Instance {
            ip,
            port: port,
            namespace_id,
            weight: String::from("1"),
            enabled: String::from("true"),
            healthy: String::from("true"),
            metadata,
            cluster_name: String::from("DEFAULT"),
            service_name: service_name,
            group_name: group_name,
            ephemeral: String::from("true"),
        },
        url: RequestUrl::PutHealthInstance,
        headers: Default::default(),
        content_type: Default::default(),
    };

    tokio::spawn(async move {
        loop {
            let instance_res = normal_handler(&instance_req).await;
            info!("instance_res={:?}", instance_res);
            let instance_health_res = normal_handler(&instance_health).await;
            info!("instance_health={:?}", instance_health_res);
            tokio::time::sleep(Duration::from_secs(15)).await;
        }
    });
}

async fn register_service(
    service_name: &String,
    group_name: &String,
    namespace_id: &String,
    protect_threshold: &String,
    metadata: &String,
    selector: &String,
) {
    let service_name = service_name.clone();
    let group_name = group_name.clone();
    let namespace_id = namespace_id.clone();
    let protect_threshold = protect_threshold.clone();
    let metadata = metadata.clone();
    let selector = selector.clone();

    let req = Request {
        data: Service {
            service_name,
            group_name,
            namespace_id,
            protect_threshold,
            metadata,
            selector,
        },
        url: RequestUrl::GetService,
        headers: Default::default(),
        content_type: Default::default(),
    };
    tokio::spawn(async move {
        loop {
            //查询服务是否存在
            let res = normal_handler(&req).await;
            match res {
                Ok(data) => {
                    let data = data.data.unwrap();
                    let service: serde_json::Result<ServiceInfoRes> = serde_json::from_str(&data);
                    match service {
                        Ok(_) => {
                            tracing::info!("服务已存在 {:?}", &service);
                        }
                        Err(_) => {
                            // create nacos service
                            let req = Request {
                                url: RequestUrl::PostService,
                                ..req.clone()
                            };

                            let res = normal_handler(&req).await;
                            info!("创建服务结束 res={:?}", res);
                        }
                    }
                }
                Err(_) => panic!("注册失败"),
            }
            tokio::time::sleep(Duration::from_secs(15)).await;
        }
    });
}

#[cfg(test)]
mod tests {

    use std::collections::BTreeMap;

    use tracing::log::info;

    use crate::log_init;

    use super::*;
    #[tokio::test]
    async fn test_normal_handler() {
        log_init();
        info!("获取配置开始");
        let get_configs = Request {
            data: Configs::default(),
            url: RequestUrl::GetConfigs,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let get_config_res = normal_handler(&get_configs).await;

        info!("获取配置结束 {get_config_res:?}");
        info!("监听配置开始");
        // let config = Configs::default();
        // let mut headers = HeaderMap::new();
        // headers.insert("Long-Pulling-Timeout", 3.into());
        // let post_configs = Request {
        //     data: ListeningConfigs::new(&config, "f53d8f020f43e8265612bcb12ec88c1e"),
        //     url: RequestUrl::PostConfigLinsten,
        //     headers: Some(headers),
        //     content_type: RequestContentType::Form,
        // };
        // let post_configs_res = normal_handler(&post_configs).await.unwrap();
        // tracing::info!("监听配置结束 {post_configs_res:#?}");

        info!("发布配置开始");
        let mut map = BTreeMap::new();
        map.insert("x1".to_string(), 1.0);
        map.insert("y1".to_string(), 2333.0);

        // Serialize it to a YAML string.
        let yaml = serde_yaml::to_string(&map).unwrap();
        let publish_config = Request {
            data: ConfigsPublish {
                content: yaml.replace("\\", ""),
                content_type: "yaml".to_string(),
                configs: Configs::default(),
            },
            url: RequestUrl::PostConfigs,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let publish_config_res = normal_handler(&publish_config).await;
        info!("发布配置结束 {publish_config_res:?}");

        info!("删除配置开始");
        let del_configs = Request {
            data: Configs::default(),
            url: RequestUrl::DeleteConfigs,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let del_config_res = normal_handler(&del_configs).await;
        info!("删除配置结束 {del_config_res:?}");
        info!("查询配置历史版本开始");
        let req = Request {
            data: HistoryConfigs::default(),
            url: RequestUrl::GetHistoryConfigs,
            headers: Default::default(),
            content_type: Default::default(),
        };

        let res = normal_handler(&req).await.unwrap();
        let res_1: HistoryConfigsRes = serde_json::from_str(&res.data.unwrap()).unwrap();
        tracing::info!("查询配置历史版本结束 {res_1:#?}");

        info!("查询配置历史版本详情开始");
        let req = Request {
            data: HistoryConfigInfo::new(214.to_string().to_string(), Configs::default()),
            url: RequestUrl::GetHistoryConfigsInfo,
            headers: Default::default(),
            content_type: Default::default(),
        };

        let res = normal_handler(&req).await.unwrap();
        let res_1: HistoryConfigInfoRes = serde_json::from_str(&res.data.unwrap()).unwrap();
        tracing::info!("查询配置历史版本详情结束 {res_1:#?}");

        info!("查询配置上一版本信息(1.4起)开始");
        let req = Request {
            data: PreviousHistoryConfigInfo::new(res_1.id, Configs::default()),
            url: RequestUrl::GetHistoryPreviousConfigsInfo,
            headers: Default::default(),
            content_type: Default::default(),
        };

        let res = normal_handler(&req).await;
        info!("查询配置上一版本信息(1.4起)结束{res:?}");

        info!("注册实例开始");
        let req = Request {
            data: Instance::default(),
            url: RequestUrl::PostServiceInstance,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("注册实例结束{res:?}");
        info!("注销实例开始");
        let req = Request {
            data: Instance::default(),
            url: RequestUrl::DeleteServiceInstance,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("注销实例结束{res:?}");

        info!("修改例开始");
        let req = Request {
            data: Instance::default(),
            url: RequestUrl::PutServiceInstance,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("修改实例结束{res:?}");

        info!("查询实例列表开始");
        let req = Request {
            data: InstanceQueryList::default(),
            url: RequestUrl::GetServiceInstanceList,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("查询实例列表结束{res:?}");

        info!("查询实例详情开始");
        let req = Request {
            data: Instance::default(),
            url: RequestUrl::GetServiceInstance,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("查询实例详情结束{res:?}");

        info!("发送实例心跳开始");
        let mut map = HashMap::new();
        map.insert(
            "preserved.register.source".to_string(),
            "SPRING_CLOUD".to_string(),
        );
        let beat = Beat {
            cluster: Default::default(),
            ip: "10.0.16.24".to_string(),
            metadata: Some(map),
            port: 8082,
            scheduled: true,
            service_name: "service-job-gateway".to_string(),
            weight: 1,
        };
        let beat_json = serde_json::to_string(&beat).unwrap();
        let json = urlencoding::encode(&beat_json).into_owned();
        let req = Request {
            data: InstanceBeat {
                service_name: Some("service-job-gateway".to_string()),
                ip: Some("10.0.16.24".to_string()),
                port: Some("8082".to_string()),
                namespace_id: Default::default(),
                group_name: Default::default(),
                ephemeral: Default::default(),
                beat: Some(json),
            },
            url: RequestUrl::PutServiceInstanceBeat,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("发送实例心跳结束{res:?}");

        info!("创建服务开始");
        let req = Request {
            data: Service::default(),
            url: RequestUrl::PostService,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("创建服务结束{res:?}");
        info!("修改服务开始");
        let req = Request {
            data: Service::default(),
            url: RequestUrl::PutService,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("修改服务结束{res:?}");

        info!("查询服务开始");
        let req = Request {
            data: Service::default(),
            url: RequestUrl::GetService,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await.unwrap();

        let res_1: ServiceInfoRes = serde_json::from_str(&res.data.unwrap()).unwrap();
        info!("查询服务结束{res_1:?}");

        info!("删除服务开始");
        let req = Request {
            data: Service::default(),
            url: RequestUrl::DeleteService,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("删除服务结束{res:?}");

        info!("查询服务列表开始");
        let req = Request {
            data: ServiceListQuery::default(),
            url: RequestUrl::GetServiceList,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("查询服务列表开始{res:?}");

        info!("查询系统开关");
        let req = Request {
            data: OperatorSwitches {
                entry: Some(String::default()),
                value: Some(String::default()),
                debug: Some(String::default()),
            },
            url: RequestUrl::GetSysOperterSwitch,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await.unwrap();

        let res_1: OperatorSwitchesRes = serde_json::from_str(&res.data.unwrap()).unwrap();
        info!("查询系统开关{res_1:?}");

        info!("修改系统开关");
        let req = Request {
            data: OperatorSwitches {
                entry: Some("pushEnabled".to_string()),
                value: Some("true".to_string()),
                debug: Some("false".to_string()),
            },
            url: RequestUrl::PutSysOperterSwitch,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await.unwrap();

        info!("修改系统开关{res:?}");

        info!("查看系统当前数据指标");
        let req = Request {
            data: OperatorMetrics {},
            url: RequestUrl::GetSysOperterMetrics,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await.unwrap();

        let res_1: OperatorMetricsRes = serde_json::from_str(&res.data.unwrap()).unwrap();
        info!("查看系统当前数据指标{res_1:?}");

        info!("查看当前集群Server列表");
        let req = Request {
            data: OperatorServers {
                healthy: Some("true".to_string()),
            },
            url: RequestUrl::GetSysOperterMetrics,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await.unwrap();

        let res_1: OperatorServersRes = serde_json::from_str(&res.data.unwrap()).unwrap();
        info!("查看当前集群Server列表{res_1:?}");

        info!("查看当前集群leader");
        let req = Request {
            data: RaftLeader {},
            url: RequestUrl::GetSysRaftLeader,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;

        // let res_1: RaftLeaderRes = serde_json::from_str(&res.data.unwrap()).unwrap();
        info!("查看当前集群leader{res:?}");

        info!("更新实例的健康状态");
        let req = Request {
            data: InstanceHealthy::default(),
            url: RequestUrl::PutHealthInstance,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;

        info!("更新实例的健康状态{res:?}");

        info!("批量更新实例元数据(Beta)");
        info!("批量删除实例元数据(Beta)");
        info!("查询命名空间列表开始");
        let req = Request {
            data: ConsoleNamespaces::default(),
            url: RequestUrl::GetConsoleNameSpaces,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("查询命名空间列表结束{:?}", &res);
        let json = res.unwrap().data.unwrap();
        let res_1: ConsoleNamespacesRes = serde_json::from_str(json.as_str()).unwrap();
        info!("查询命名空间列表结束{res_1:?}");

        info!("创建命名空间");
        let req = Request {
            data: ConsoleNamespaces {
                custom_namespace_id: Some("123455".to_string()),
                namespace_name: Some("123455".to_string()),
                namespace_desc: Some("123455".to_string()),
                namespace_id: Some("".to_string()),
                namespace_show_name: Some("".to_string()),
                namespace: Some("".to_string()),
            },
            url: RequestUrl::PostConsoleNameSpaces,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("创建命名空间结束{:?}", &res);

        info!("修改命名空间");
        let req = Request {
            data: ConsoleNamespaces {
                custom_namespace_id: Some("".to_string()),
                namespace_name: Some("".to_string()),
                namespace_desc: Some("ssssssssaaaa".to_string()),
                namespace_id: Some("".to_string()),
                namespace_show_name: Some("ssssssssss".to_string()),
                namespace: Some("123455".to_string()),
            },
            url: RequestUrl::PutConsoleNameSpaces,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("修改命名空间{:?}", &res);

        info!("删除命名空间");
        let req = Request {
            data: ConsoleNamespaces {
                custom_namespace_id: Some("".to_string()),
                namespace_name: Some("".to_string()),
                namespace_desc: Some("".to_string()),
                namespace_id: Some("123455".to_string()),
                namespace_show_name: Some("".to_string()),
                namespace: Some("".to_string()),
            },
            url: RequestUrl::DeleteConsoleNameSpaces,
            headers: Default::default(),
            content_type: Default::default(),
        };
        let res = normal_handler(&req).await;
        info!("删除命名空间{:?}", &res);
    }
}
